#ifndef DEBUGGER_DEFS_H
#define DEBUGGER_DEFS_H

#include <wx/string.h>
#include <wx/dynarray.h>
#include <deque>
#include <vector>
#include "debuggermanager.h"

class DebuggerDriver;

extern const int DEBUGGER_CURSOR_CHANGED;
extern const int DEBUGGER_SHOW_FILE_LINE;

struct Cursor {
  Cursor() : line( -1 ), changed( false ) {}
  wxString file;
  wxString address;
  wxString function;
  long int line;
  bool changed;
};

class DebuggerCmd {
  public:
    DebuggerCmd( DebuggerDriver* driver, const wxString& cmd = _T( "" ), bool logToNormalLog = false );
    virtual ~DebuggerCmd() {}
    virtual void Action() {}
    virtual void ParseOutput( const wxString& output );
    virtual bool IsContinueCommand() const { return false; }
    wxString m_Cmd;
  protected:
    DebuggerDriver* m_pDriver;
    bool m_LogToNormalLog;
};

class DebuggerInfoCmd : public DebuggerCmd {
  public:
    DebuggerInfoCmd( DebuggerDriver* driver, const wxString& cmd, const wxString& title )
      : DebuggerCmd( driver, cmd ),
        m_Title( title ) {
      m_Cmd = cmd;
    }
    virtual ~DebuggerInfoCmd() {}

    virtual void ParseOutput( const wxString& output );
    wxString m_Title;
};

class DebuggerContinueBaseCmd : public DebuggerCmd {
  public:
    DebuggerContinueBaseCmd( DebuggerDriver* driver, const wxString& cmd = _T( "" ), bool logToNormalLog = false ) :
      DebuggerCmd( driver, cmd, logToNormalLog ) {
    }

    bool IsContinueCommand() const { return true; }
};

class DbgCmd_UpdateWatchesTree : public DebuggerCmd {
  public:
    DbgCmd_UpdateWatchesTree( DebuggerDriver* driver );
    virtual ~DbgCmd_UpdateWatchesTree() {}
    virtual void Action();
};

struct DebuggerBreakpoint : cbBreakpoint {
  enum BreakpointType {
    bptCode = 0,
    bptFunction,
    bptData
  };

  DebuggerBreakpoint()
    : type( bptCode ),
      line( 0 ),
      index( -1 ),
      temporary( false ),
      enabled( true ),
      active( true ),
      useIgnoreCount( false ),
      ignoreCount( 0 ),
      useCondition( false ),
      wantsCondition( false ),
      address( 0 ),
      alreadySet( false ),
      breakOnRead( false ),
      breakOnWrite( true ),
      userData( 0 ) {}

  virtual void SetEnabled( bool flag );
  virtual wxString GetLocation() const;
  virtual int GetLine() const;
  virtual wxString GetLineString() const;
  virtual wxString GetType() const;
  virtual wxString GetInfo() const;
  virtual bool IsEnabled() const;
  virtual bool IsVisibleInEditor() const;
  virtual bool IsTemporary() const;
  BreakpointType type;
  wxString filename;
  wxString filenameAsPassed;
  int line;
  long int index;
  bool temporary;
  bool enabled;
  bool active;
  bool useIgnoreCount;
  int ignoreCount;
  bool useCondition;
  bool wantsCondition;
  wxString condition;
  wxString func;
  unsigned long int address;
  bool alreadySet;
  wxString lineText;
  wxString breakAddress;
  bool breakOnRead;
  bool breakOnWrite;
  void* userData;
};
typedef std::deque<cb::shared_ptr<DebuggerBreakpoint> > BreakpointsList;

enum WatchFormat {
  Undefined = 0,
  Decimal,
  Unsigned,
  Hex,
  Binary,
  Char,
  Float,
  Last,
  Any
};

class GDBWatch : public cbWatch {
  public:
    GDBWatch( wxString const &symbol );
    virtual ~GDBWatch();
  public:
    virtual void GetSymbol( wxString &symbol ) const;
    virtual void GetValue( wxString &value ) const;
    virtual bool SetValue( const wxString &value );
    virtual void GetFullWatchString( wxString &full_watch ) const;
    virtual void GetType( wxString &type ) const;
    virtual void SetType( const wxString &type );
    virtual wxString const & GetDebugString() const;
    wxString MakeSymbolToAddress() const override;
    bool IsPointerType() const override;
  public:
    void SetDebugValue( wxString const &value );
    void SetSymbol( const wxString& symbol );
    void SetFormat( WatchFormat format );
    WatchFormat GetFormat() const;
    void SetArray( bool flag );
    bool IsArray() const;
    void SetArrayParams( int start, int count );
    int GetArrayStart() const;
    int GetArrayCount() const;
    void SetForTooltip( bool flag = true );
    bool GetForTooltip() const;
  protected:
    virtual void DoDestroy();
  private:
    wxString m_symbol;
    wxString m_type;
    wxString m_raw_value;
    wxString m_debug_value;
    WatchFormat m_format;
    int m_array_start;
    int m_array_count;
    bool m_is_array;
    bool m_forTooltip;
};

typedef std::vector<cb::shared_ptr<GDBWatch> > WatchesContainer;

bool IsPointerType( wxString type );
wxString CleanStringValue( wxString value );

#endif
